package com.zhang.zxx.boot.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhang.zxx.boot.common.constant.Constant;
import com.zhang.zxx.boot.common.core.aspect.WebLog;
import com.zhang.zxx.boot.common.enums.MsgEunm;
import com.zhang.zxx.boot.common.enums.UserInfoStatusEnum;
import com.zhang.zxx.boot.common.exception.BusinessException;
import com.zhang.zxx.boot.common.util.BPwdEncoderUtil;
import com.zhang.zxx.boot.domain.dto.LoginInputDTO;
import com.zhang.zxx.boot.domain.dto.LoginOutputDTO;
import com.zhang.zxx.boot.domain.dto.UserDTO;
import com.zhang.zxx.boot.domain.dto.UserPageDTO;
import com.zhang.zxx.boot.entity.DO.SysRole;
import com.zhang.zxx.boot.entity.DO.SysUserInfo;
import com.zhang.zxx.boot.mapper.SysUserInfoMapper;
import com.zhang.zxx.boot.service.SysDeptService;
import com.zhang.zxx.boot.service.SysUserInfoService;
import com.zhang.zxx.boot.service.justimpl.AuthService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;


/**
 * 用户表: 服务类实现类
 *
 * @author zhangxiaoxiang
 * @date 2021-11-21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserInfoServiceImpl extends ServiceImpl<SysUserInfoMapper, SysUserInfo> implements SysUserInfoService {
    private final SysUserInfoMapper sysUserInfoMapper;
    private final AuthService authService;
    private final SysDeptService deptService;

    @Override
    public List<SysUserInfo> getUsers(UserDTO dto) {
        LambdaQueryWrapper<SysUserInfo> query = new LambdaQueryWrapper<>();
        Predicate<String> p = StrUtil::isNotBlank;
        query = p.test(dto.getId()) ? query.eq(SysUserInfo::getId, dto.getId()) : query;
        query = p.test(dto.getUsername()) ? query.like(SysUserInfo::getUsername, dto.getUsername()) : query;
        query = p.test(dto.getEmail()) ? query.like(SysUserInfo::getEmail, dto.getEmail()) : query;
        query = p.test(dto.getPhoneNumber()) ? query.eq(SysUserInfo::getPhoneNumber, dto.getPhoneNumber()) : query;
        return list(query);
    }

    @Override
    public IPage<SysUserInfo> sysUserInfoPage(UserPageDTO dto) {
        LambdaQueryWrapper<SysUserInfo> query = new LambdaQueryWrapper<>();
        Predicate<Object> p = ObjectUtil::isNotEmpty;
        query.eq(p.test(dto.getId()), SysUserInfo::getId, dto.getId())
                .eq(p.test(dto.getPhoneNumber()), SysUserInfo::getPhoneNumber, dto.getPhoneNumber())
                .eq(p.test(dto.getEmail()), SysUserInfo::getEmail, dto.getEmail())
                .like(p.test(dto.getUsername()), SysUserInfo::getUsername, dto.getUsername())
                .ge(p.test(dto.getStartTime()), SysUserInfo::getCreateDate, dto.getStartTime())
                .le(p.test(dto.getEndTime()), SysUserInfo::getCreateDate, dto.getEndTime());
        return this.page(dto, query);
    }

    @WebLog
    @Override
    public String login(LoginInputDTO dto) {

        SysUserInfo userInfo = super.getOne(Wrappers.lambdaQuery(SysUserInfo.class).eq(SysUserInfo::getUsername, dto.getUsername()).last("LIMIT 1"));
        if (ObjectUtil.isEmpty(userInfo) || !BPwdEncoderUtil.matches(dto.getPassword(), userInfo.getPassword())) {
            throw new BusinessException(MsgEunm.USER_ACCOUNT_OR_PASSWORD_WRONG);
        }
        if (UserInfoStatusEnum.DISABLE.code.equals(userInfo.getUserStatus())) {
            throw new BusinessException(MsgEunm.USER_DISABLE);
        }
        //拷贝一些重要属性
        LoginOutputDTO loginOutputDTO = new LoginOutputDTO()
                .setId(userInfo.getId())
                .setDeptId(userInfo.getDeptId())
                .setUsername(userInfo.getUsername())
                .setNickName(userInfo.getNickName())
                .setUserType(userInfo.getUserType())
                .setEmail(userInfo.getEmail())
                .setPhoneNumber(userInfo.getPhoneNumber())
                .setSex(userInfo.getSex())
                .setAvatarPath(userInfo.getAvatarPath())
                .setUserStatus(userInfo.getUserStatus())
                .setDeptName(userInfo.getDeptName())
                .setCreateDate(userInfo.getCreateDate());
        // 设置权限
        loginOutputDTO.setResources(authService.getAuthRoleAndResourceByUserId(userInfo.getId()));
        if (StrUtil.isNotBlank(userInfo.getDeptId())) {
            loginOutputDTO.setDeptName(deptService.getById(userInfo.getDeptId()).getName());
        }
        List<SysRole> authRoleListByUserId = sysUserInfoMapper.selectAuthRoleListByUserId(userInfo.getId());
        if (CollUtil.isNotEmpty(authRoleListByUserId)) {
            loginOutputDTO.setRoleName(CollUtil.join(authRoleListByUserId.stream().map(SysRole::getRoleName).collect(Collectors.toList()), ","));
        }
        // sa-token 登录
        StpUtil.login(userInfo.getId());
        // 获取token
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 获取session
        SaSession session = StpUtil.getSession();
        // 设置用户信息
        session.set(Constant.SESSION_USER_KEY, loginOutputDTO);
        return tokenInfo.getTokenValue();
    }
}
